iT邦幫忙

2023 iThome 鐵人賽

DAY 21
1
Cloud Native

時光之鏡:透視過去、現在與未來的 Observability系列 第 21

Jaeger - 系統軌跡,無所遁形

  • 分享至 

  • xImage
  •  

Jaeger Logo

資訊處理流程 生成 收集 儲存 使用
Jaeger

Jaeger 是由 Uber 於 2015 年 8 月開始開發的分散式追蹤(Distributed Tracing)工具。它具備完整的資料收集機制和查詢介面,而主要的儲存方式則支援 Cassandra 和 Elasticsearch。在 2017 年 9 月,Jaeger 成為 CNCF 的孵化專案,後於 2019 年 10 月晉升為畢業專案。除了支援 Jaeger 本身的自訂格式,它也支援 OpenTelemetry、Zipkin 等其他 API。過去,Jaeger 有自己維護的 SDK(Client Library),但該 SDK 自 2022 年 1 月發布最後一版後便不再進行維護(Sunsetting Jaeger clients),官方建議改用 OpenTelemetry SDK。

Pipeline

Jaeger 作者 Yuri Shkuro 在 2017 年於 Uber Blog 發表了「Evolving Distributed Tracing at Uber Engineering 」,這篇文章介紹了 Jaeger 的開發源由與發展軌跡。Uber 最初有一個僅供內部使用的第一代追蹤系統,名為 Merckx。但隨著系統變得越來越複雜,Merckx 不再符合需求。於是參考了 Dapper 與 Zipkin 的設計概念設計出了 Jaeger。Jaeger 是德文的獵人或狩獵助手的意思,發音為(ˈyā-gər),相當貼近分散式追蹤的主題,如追蹤、偵查和解決問題。

Concepts

Architecture

Jaeger 官網的 Getting Started 提供了一個 all-in-one 的版本。這個版本可以透過單一 Binary 或 Container 來啟動 Jaeger,並將所有資料儲存在記憶體中。但這個版本僅適用於初步體驗,因為一旦關閉 Jaeger,所有的資料就會遺失。在 Production 環境中,Jaeger 的後端通常會以分散式系統的方式分有多個 Component 運行,如下圖所示。

Architecture
圖片來源:Jaeger

在本篇 Lab 所使用的範例即基於這樣的架構建立的,是參考官方的 docker compose example 範例修改而成。

這個架構主要包含三個部分:

  1. Jaeger Collector:負責接收來自 OpenTelemetry SDK 發送的 Trace Data,並經過處理後儲存到 Storage。
  2. Storage:用於儲存 Trace Data。Jaeger 支援 Cassandra、Elasticsearch、Kafka、Memory Storage,以及 Storage Plugin 等多種儲存方式。其中,Kafka 主要適用於高流量的情況,但仍需搭配如 Cassandra、Elasticsearch 等其他能提供儲存功能的服務。
  3. Jaeger Query:提供 UI 查看 Trace Data。

Jaeger UI

在 Jaeger 較舊的版本中,可能還會看到一個名為 Jaeger Agent 的 Component。它主要用於加工和轉發 Trace Data,但自 1.43 版之後已經不再維護。若需類似功能,可選擇使用 OpenTelemetry Collector

API 選擇

Jaeger 因具有較長的發展歷史,因此支援多種 API。了解自己所使用的 Trace Data 傳遞方式與格式極為重要,否則容易陷入無盡的排列組合除錯迴圈。標準的判斷方式為:確保 SDK 所選用的 Protocol 和格式與 Jaeger Collector 的 Port 是否相符。以下為常用的四個 Protocol 與 Port 對應,詳細說明可參考官方文件

Collector Port Collector Protocol Data API 功能
14250 gRPC Protobuf via gRPC 接收 Jaeger model.proto 格式的 Trace Data
14268 HTTP Thrift over HTTP 接收 Jaeger jaeger.thrift 格式的 Trace Data,並須加上 /api/traces Path
4317 gRPC OpenTelemetry Protocol 接收 OpenTelemetry 格式的 Trace Data,但 Collector 啟動時必須增加 --collector.otlp.enabled=true 參數啟用
4318 HTTP OpenTelemetry Protocol 接收 OpenTelemetry 格式的 Trace Data,但 Collector 啟動時必須增加 --collector.otlp.enabled=true 參數啟用

從 v1.35 版本起,Jaeger Collector 開始支援 OpenTelemetry Protocol(OTLP)。因此,不再需要透過 OpenTelemetry Collector 轉換格式,可以直接使用 OpenTelemetry SDK 發送 Trace Data 至 Jaeger Collector。由於 Jaeger 開始正式支援 OTLP,OpenTelemetry SDK 中大部分支援 Jaeger 的 API 都將在 2023 年 7 月之後停止維護,未來也可能會被移除。因此,建議在選擇 API 時,優先使用 OTLP。

Sampling

在 Distributed Tracing 中,每個 Request 都會產生大量的 Trace Data。若每筆 Trace 都進行儲存,會造成儲存成本過高。因此,需要透過採樣(Sampling)方式來只保留部分 Trace。Jaeger 提供了兩種採樣方式:

  1. File-based Sampling:根據設定檔中的規則來決定是否儲存 Trace Data,包括基於機率的 probabilistic 和基於每秒頻率的 ratelimiting 兩種方式。例如,可以設定讓 service foo 的 Trace Data 只有 80% 的機率被收集,或是每秒只收集 2 筆 service bar 的 Trace Data。
  2. Adaptive Sampling:根據流量動態調整採樣比率,需要額外儲存流量的統計資料。可選擇直接儲存在 Memory 或 Cassandra。

採樣的設定方式是由 Jaeger Collector 提供採樣策略,並透過 sampling.proto 格式供服務輪尋取得。根據這些採樣策略,SDK 會決定是否要送出 Trace Data 給 Jaeger Collector。

Sampling Config

SDK 需設定 JaegerRemoteSampler,並指定 Jaeger Collector 提供採樣策略的 endpoint,一般為 http://<jaeger-collector>:14268/api/sampling<jaeger-collector>:14250。也可透過環境變數 OTEL_TRACES_SAMPLEROTEL_TRACES_SAMPLER_ARG 進行設定,詳情可參考官方文件

Lab

範例程式碼:21-jaeger

Lab Architecture

在範例中使用了四個方式來發送 Trace Data:

A. 透過 gRPC 發送 OTLP Trace Data 至 Jaeger Collector 的 4317 Port
B. 透過 HTTP 發送 OTLP Trace Data 至 Jaeger Collector 的 4318 Port
C. 透過 gRPC 發送 jaeger.thrift Trace Data 至 Jaeger Collector 的 14268 Port
D. 透過 HTTP 發送 model.proto Trace Data 至 Jaeger Collector 的 14250 Port

Jaeger Collector 會將 Trace Data 寫入 DB,Jaeger Query 則是從 DB 讀取 Trace Data 並提供 UI 查看。

Quick Start

  1. 啟動所有服務

    docker-compose up -d
    
  2. 檢視服務

    1. 因 Cassandra 需要一些時間初始化,確認 Jaeger Collector 與 Jaeger Query 已啟動後,再繼續下一步

      docker-compose ps
      
    2. FastAPI App

      1. app-a: http://localhost:8000
      2. app-b: http://localhost:8001
      3. app-c: http://localhost:8002
      4. app-d: http://localhost:8003
    3. Jaeger UI: http://localhost:16686

      1. 選擇 Service 後點選 Find Traces,即可看到 Trace Data

      2. 透過瀏覽器對 application 的 /chain 發送 Request,可以在 Trace 資訊中看到 app-aapp-bapp-c 互相呼叫的順序

        1. app-a: http://localhost:8000/chain
        2. app-b: http://localhost:8001/chain
        3. app-c: http://localhost:8002/chain
        4. app-d: http://localhost:8003/chain
      3. 或是使用 k6 發送 Request

        k6 run --vus 1 --duration 300s k6-script.js
        
    4. Grafana: http://localhost:3000,登入帳號密碼為 admin/admin

      1. 點擊左上 Menu > Explore,左上 Data Source 選擇 Jaeger,可以查詢 Jaeger 的 Trace Data
  3. 關閉所有服務

    docker-compose down
    

Goals

  1. 建立 Jaeger Components
    1. Jaeger Collector: 接收 Application 發送的 Trace Data
    2. Jaeger Query: 提供 UI 查看 Trace Data
    3. Cassandra: 儲存 Trace Data
    4. Cassandra Schema: 初始化 Cassandra DB
  2. FastAPI 透過 OpenTelemetry 發送 Trace Data 至 Jaeger Collector
    1. app-a: 透過 gRPC 發送 OTLP Trace Data 至 Jaeger Collector 的 4317 Port
    2. app-b: 透過 HTTP 發送 OTLP Trace Data 至 Jaeger Collector 的 4318 Port
    3. app-c: 透過 gRPC 發送 jaeger.thrift Trace Data 至 Jaeger Collector 的 14268 Port
    4. app-d: 透過 HTTP 發送 model.proto Trace Data 至 Jaeger Collector 的 14250 Port
  3. 建立 Grafana Dashboard 讀取 Jaeger Data Source 查看 Trace Data

小結

Jaeger,作為一個經驗豐富並已晉升為 CNCF Graduated Project 的分散式追蹤系統,已被廣泛應用於生產環境中,同時也與時俱進和 OpenTelemetry 緊密結合,這都讓它能夠持續在微服務領域中發光發熱。

在深入研究 Jaeger 的過程中,才認識了 Jaeger 之父 Yuri Shkuro。他不僅對 Jaeger 有著重要的貢獻,還是 OpenTracingOpenTelemetry 的 Co-founder 以及 W3C Trace ContextBaggage 規範的共同作者,更出版了一本 Mastering Distributed Tracing 分享他對 Tracing 的見解,從這裡更可以感受到這些天才橫溢的工程師們,真的是能夠憑一己之力推動整個領域的發展。

參考資料

  1. Evolving Distributed Tracing at Uber Engineering
  2. Jaeger Turns Five: A Tribute to Project Contributor
  3. Jaeger Project Journey Report
  4. FastAPI Tracing with Jaeger through OpenTelemetry

上一篇
Tempo - 小孩才做選擇,Trace 我全都要
下一篇
OpenTelemetry Collector — 依賴反轉,解耦應用程式與儲存後端
系列文
時光之鏡:透視過去、現在與未來的 Observability30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言